#include "miniutil/strutil.h"
#include "miniutil/commandline.h"

namespace miniutil { namespace util {


CTypeCommandLineParser::CTypeCommandLineParser(const std::string& format)
{
    SetFormat(format);
}

CTypeCommandLineParser::CTypeCommandLineParser(std::vector<OptionIndicator> voptions)
{
    mvoptions = voptions;
}


int CTypeCommandLineParser::SetFormat(const std::string& format)
{
    for(unsigned int i=0; i< format.length();)
    {
        OptionIndicator opt;
        opt.shortopt = format[i];
        i++;
        if(format[i] == ':')
        {
            opt.hasarg = true;
            i++;
        }
        else
        {
            opt.hasarg = false;
        }
        mvoptions.push_back(opt);          
    }
    return 0;
}

//not include first para APPLICATION NAME
int CTypeCommandLineParser::ParseParaLine(const std::string& paraline)
{
    mmparas.clear();
    std::vector<std::string> vcmds = miniutil::strutil::split(paraline," ");
    for(unsigned int i=0; i< vcmds.size();)
    {
        if(vcmds[i].length() < 2)
        {
            //error
            return -1;
        }
        
        if(vcmds[i][0] != '-')
        {
            mvnotopt.push_back(vcmds[i]);
            i++;
            continue;
        }
        
        OptionIndicator opt;
        
        if(vcmds[i].substr(2) == "--")
        {
            for(unsigned int j=0; j< mvoptions.size(); j++)
            {
                if(vcmds[i].length() > 2 && mvoptions[j].longopt == vcmds[i].substr(2))
                {
                    opt = mvoptions[j];
                    break;
                }     
            }
        }
        else //short, support -cpu as -c -p -u
        {
            for(unsigned k=1; k< vcmds[i].size(); k++)
            {
                for(unsigned int j=0; j< mvoptions.size(); j++)
                {
                    if(mvoptions[j].shortopt[0] == vcmds[i][k])
                    {
                        opt = mvoptions[j];
                        break;
                    }
                }
                if(opt.shortopt.empty())
                    continue;
                if(!opt.hasarg)
                    mmparas.insert(std::make_pair(opt.shortopt, ""));
                else
                    break; //find args
            }           
        }
        i++;
        if(i >= vcmds.size())
            break;

        std::string vle;
        if(opt.hasarg)
        {
            vle = vcmds[i];
            i++;
        }
        mmparas.insert(std::make_pair(opt.shortopt, vle));
    }
    return 0;
}


int CTypeCommandLineParser::ParseCommandLine(const std::string& cmdline)
{
    std::string cnl = cmdline;
    std::string::size_type pos1 = cmdline.find_first_not_of(" ");
    std::string::size_type pos2 = cmdline.find_first_of(" ",pos1);
    appname = cmdline.substr(pos1, pos2-pos1);
    pos1 = cmdline.find_first_not_of(" ", pos2);
    std::string paraline = cmdline;
    if(pos1 != std::string::npos)
        paraline = cmdline.substr(pos1);
    return ParseParaLine(paraline);
}

int CTypeCommandLineParser::ParseCommandLine(int argc, char** argv)
{
    std::string cmdline = argv[0];
    for(int i=1; i< argc; i++)
    {
        cmdline += " ";
        cmdline += argv[i];
    }
    return ParseCommandLine(cmdline);
}

int CTypeCommandLineParser::CheckPara(const std::string& key, std::string& value)
{
    if(mmparas.find(key) == mmparas.end())
        return -1;
    else
    {
        value = mmparas[key];
        return 0;
    }
}


} }
